﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace UIPrototyper
{
    /// <summary>
    /// Interaction logic for SelectionUC.xaml
    /// </summary>
    public partial class SelectionUC : UserControl, ISelectable
    {
        Operations operation = Operations.None;
        ISelectable associatedControl;

        public ISelectable AssociatedControl
        {
            get { return associatedControl; }
        }

        public Operations Operation
        {
            get { return operation; }
            set { operation = value; }
        }

        public SelectionUC(ISelectable pControl)
        {
            InitializeComponent();

            this.associatedControl = pControl;

            ((FrameworkElement)pControl).Measure(new Size(800, 600));

            this.Margin = new Thickness(((FrameworkElement)pControl).Margin.Left - 5, ((FrameworkElement)pControl).Margin.Top - 5, 0, 0);
            this.Width = ((FrameworkElement)pControl).Width + 10;
            this.Height = ((FrameworkElement)pControl).Height + 10;

            this.Measure(new Size(800, 600));

            ((IChanged)pControl).iChanged += new ChangedHandler(SelectionUC_iChanged);

            this.LayoutUpdated += new EventHandler(SelectionUC_LayoutUpdated);
        }

        void SelectionUC_LayoutUpdated(object sender, EventArgs e)
        {
            if (AssociatedControl.GetType() == typeof(CustomImage))
            {
                if (((CustomImage)AssociatedControl).Source == null)
                {
                    SetError(Visibility.Visible);
                }
                else
                {
                    SetError(Visibility.Hidden);
                }
            }
        }

        void SelectionUC_iChanged(IChanged changedObject)
        {
            this.NoContent.Content = ((ISelectable)changedObject).Properties.Nome;

            if (changedObject.GetType() == typeof(CustomImage))
            {
                if (((CustomImage)changedObject).Source == null)
                {
                    SetError(Visibility.Visible);
                }
                else
                {
                    SetError(Visibility.Hidden);
                }
            }
        }

        private void rectMain_MouseDown(object sender, MouseButtonEventArgs e)
        {
            rectMain.Cursor = Cursors.ScrollAll;
            operation = Operations.Move;
        }

        private void rectMain_MouseUp(object sender, MouseButtonEventArgs e)
        {
            rectMain.Cursor = Cursors.Hand;
            operation = Operations.None;
        }

        private void rectUpperLeft_MouseDown(object sender, MouseButtonEventArgs e)
        {
            operation = Operations.ResizeDTopLeft;
        }

        private void rectUpperRight_MouseDown(object sender, MouseButtonEventArgs e)
        {
            operation = Operations.ResizeDTopRight;
        }

        private void rectLowerLeft_MouseDown(object sender, MouseButtonEventArgs e)
        {
            operation = Operations.ResizeDBottomLeft;
        }

        private void rectLowerRight_MouseDown(object sender, MouseButtonEventArgs e)
        {
            operation = Operations.ResizeDBottomRight;
        }

        private void rectTop_MouseDown(object sender, MouseButtonEventArgs e)
        {
            operation = Operations.ResizeVTop;
        }

        private void rectLeft_MouseDown(object sender, MouseButtonEventArgs e)
        {
            operation = Operations.ResizeHLeft;
        }

        private void rectRight_MouseDown(object sender, MouseButtonEventArgs e)
        {
            operation = Operations.ResizeHRight;
        }

        private void rectBottom_MouseDown(object sender, MouseButtonEventArgs e)
        {
            operation = Operations.ResizeVBottom;
        }

        private new void MouseUp(object sender, MouseButtonEventArgs e)
        {
            operation = Operations.None;
        }

        public void SetMargin(Thickness pMargin)
        {
            this.Margin = pMargin;
            ((FrameworkElement)this.associatedControl).Margin = new Thickness(pMargin.Left + 5, pMargin.Top + 5, pMargin.Right, pMargin.Bottom);
        }

        public void SetWidth(double pWidth)
        {
            pWidth = pWidth < 10 ? 10 : pWidth;
            this.Width = pWidth;
            ((FrameworkElement)this.associatedControl).Width = (pWidth - 10) < 0 ? 0 : pWidth - 10;
        }

        public void SetHeight(double pHeight)
        {
            pHeight = pHeight < 10 ? 10 : pHeight;
            this.Height = pHeight;
            ((FrameworkElement)this.associatedControl).Height = (pHeight - 10) < 0 ? 0 : pHeight - 10;
        }

        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            System.Windows.Forms.MessageBox.Show(((MenuItem)sender).Header.ToString());
        }

        public virtual void Move(Point mousePosition, ref Point startPosition)
        {
            double leftMarginDifference = CalculateMarginDifference(this.Width, mousePosition.X, startPosition.X);
            double topMarginDifference = CalculateMarginDifference(this.Height, mousePosition.Y, startPosition.Y);
            double widthDifference = mousePosition.X - startPosition.X;
            double heightDifference = mousePosition.Y - startPosition.Y;

            switch (this.Operation)
            {
                case Operations.Move:
                    this.SetMargin(new Thickness(this.Margin.Left + leftMarginDifference,
                        this.Margin.Top + topMarginDifference, 0, 0));
                    break;

                case Operations.ResizeDTopLeft:
                    this.SetMargin(new Thickness(this.Margin.Left + leftMarginDifference,
                        this.Margin.Top + topMarginDifference, 0, 0));
                    this.SetWidth(this.Width - widthDifference);
                    this.SetHeight(this.Height - heightDifference);
                    break;

                case Operations.ResizeDTopRight:
                    this.SetMargin(new Thickness(this.Margin.Left, this.Margin.Top + topMarginDifference, 0, 0));
                    this.SetWidth(this.Width + widthDifference);
                    this.SetHeight(this.Height - heightDifference);
                    break;

                case Operations.ResizeDBottomLeft:
                    this.SetMargin(new Thickness(this.Margin.Left + leftMarginDifference,
                        this.Margin.Top, 0, 0));
                    this.SetWidth(this.Width - widthDifference);
                    this.SetHeight(this.Height + heightDifference);
                    break;

                case Operations.ResizeDBottomRight:
                    this.SetWidth(this.Width + widthDifference);
                    this.SetHeight(this.Height + heightDifference);
                    break;

                case Operations.ResizeVTop:
                    this.SetMargin(new Thickness(this.Margin.Left,
                        this.Margin.Top + topMarginDifference, 0, 0));
                    this.SetHeight(this.Height - heightDifference);
                    break;

                case Operations.ResizeHLeft:
                    this.SetMargin(new Thickness(this.Margin.Left + leftMarginDifference,
                        this.Margin.Top, 0, 0));
                    this.SetWidth(this.Width - widthDifference);
                    break;

                case Operations.ResizeHRight:
                    this.SetWidth(this.Width + widthDifference);
                    break;

                case Operations.ResizeVBottom:
                    this.SetHeight(this.Height + heightDifference);
                    break;
            }

            if (this.Height > 10 && this.Width > 10)
            { startPosition = mousePosition; }
            else if (this.Height > 10 && this.Width == 10)
            { startPosition.Y = mousePosition.Y; }
            else if (this.Width > 10 && this.Height == 10)
            { startPosition.X = mousePosition.X; }
        }

        private double CalculateMarginDifference(double pSize, double pMousePosition, double pStartPosition)
        {
            double marginDifference = pMousePosition - pStartPosition;

            if ((pSize - marginDifference) < 10)
                marginDifference -= (10 - (pSize - marginDifference));

            return marginDifference;
        }

        private void SetError(Visibility pVisible)
        {
            MainRectError.Visibility = pVisible;
            SmallRectError.Visibility = pVisible;
            Cross1.Visibility = pVisible;
            Cross2.Visibility = pVisible;
            NoContent.Visibility = pVisible;
        }

        #region ISelectable Members

        public string Description
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public Property Properties
        {
            get { throw new NotImplementedException(); }
        }

        #endregion

        #region IChanged Members

        public event ChangedHandler iChanged;

        public void LaunchChangedEvent(IChanged pChangedObject)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region ICopy Members

        public ISelectable Copy()
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}
